---
title: 'CSS Compositions'
permalink: '/design-system/css-compositions/index.html'
---

{% extends "design-system.njk" %}

<!-- prettier-ignore -->
{% block inner %}
<p>
  These are flexible, compositional layouts that follow the
  <a href="https://cube.fyi/composition.html">CUBE CSS composition principles</a
  >.
</p>

<h2>Configuration</h2>
<p>
  If you want to change the value of a custom property, you can either set a
  value in your context, or target the composition itself (E.G
  <code>.sidebar</code>) for extra specificity.
</p>
<p>
  The default values are fallbacks for custom properties, so are easily
  overridden.
</p>

<h2>Gutters and Spacing</h2>
<p>
  All compositions use a consistent <code>--gutter</code> Custom Property to
  manage spacing between items. You can either set a value for this in context,
  just like in the configuration section above, or you can use the
  <code>gutter</code> utility classes.
</p>

<p>
  For example, you could increase the gutter on the sidebar like this:
  <code>&lt;div class=&quot;sidebar gutter-size-2&quot;&gt;</code>.
</p>

<h2>Justification and alignment</h2>

<p>
  Each composition has a vertical and horizontal alignment Custom Property
  <strong>if applicable</strong>, but you can also use the
  <code>flex-align</code> and <code>flex-justify</code> utility classes like
  this: <code>&lt;div class=&quot;repel flex-align-center&quot;&gt;</code>.
</p>

<hr />

<h2 id="auto-grid">Auto Grid</h2>
<p><code>.auto-grid</code></p>

<p>
  A flexible layout that will create an auto-fill grid with configurable grid
  item sizes.
</p>

<h3>Configuration</h3>
<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--gutter</code></td>
        <td><code>$global-gutter</code></td>
        <td>This defines the space between each item.</td>
      </tr>
      <tr>
        <td><code>--auto-grid-min-item-size</code></td>
        <td><code>20rem</code></td>
        <td>How large each item should be, as a minimum</td>
      </tr>
      <tr>
        <td><code>--auto-grid-placement</code></td>
        <td><code>auto-fill</code></td>
        <td>
          Set either auto-fit or auto-fill to change how empty grid tracks are
          handled
        </td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>

<div class="breakout gap-top-size-1">
  <div class="auto-grid">
    <div class="bg-mid-bg pad-size-1">Item 1</div>
    <div class="bg-mid-bg pad-size-1">Item 2</div>
    <div class="bg-mid-bg pad-size-1">Item 3</div>
    <div class="bg-mid-bg pad-size-1">Item 4</div>
    <div class="bg-mid-bg pad-size-1">Item 5</div>
    <div class="bg-mid-bg pad-size-1">Item 6</div>
    <div class="bg-mid-bg pad-size-1">Item 7</div>
    <div class="bg-mid-bg pad-size-1">Item 8</div>
  </div>
</div>

<h3 id="breakout">Breakout</h3>
<p><code>.breakout</code></p>

<p>
  A layout that allows you to break a an element out of the
  bounds of its parent, with a sensible lock to prevent it bleeding out.
</p>

<h3>Configuration</h3>
<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--breakout-max-width</code></td>
        <td><code>65rem</code></td>
        <td>This defines the maximum width of the element.</td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>

<div class="region bg-mid-bg">
  <div class="breakout">
    <div class="region pad-inline-size-1 bg-reversed-bg color-reversed-text ta-center">I am a breakout element and bleed out of my parent's bounds.</div>
  </div>
</div>

<h2 id="cluster">Cluster</h2>
<p><code>.cluster</code></p>

<p>
  A layout that lets you automatically distribute items with consistent spacing,
  regardless of their size.
</p>

<h3>Configuration</h3>
<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--gutter</code></td>
        <td><code>$global-gutter</code></td>
        <td>This defines the space between each item.</td>
      </tr>
      <tr>
        <td><code>--cluster-horizontal-alignment</code></td>
        <td><code>flex-start</code></td>
        <td>
          How items should align horizontally. Can be any acceptable
          <a
            href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container"
            >flexbox alignment value.</a
          >.
        </td>
      </tr>
      <tr>
        <td><code>--cluster-vertical-alignment</code></td>
        <td><code>center</code></td>
        <td>
          How items should align vertically. Can be any acceptable
          <a
            href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container"
            >flexbox alignment value.</a
          >.
        </td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>

<div class="breakout gap-top-size-1">
  <div class="cluster">
    <div class="bg-mid-bg pad-size-1">Item 1</div>
    <div class="bg-mid-bg pad-size-1">Item 2</div>
    <div class="bg-mid-bg pad-size-1">Item 3</div>
    <div class="bg-mid-bg pad-size-1">Item 4</div>
    <div class="bg-mid-bg pad-size-1">Item 5</div>
    <div class="bg-mid-bg pad-size-1">Item 6</div>
    <div class="bg-mid-bg pad-size-1">Item 7</div>
    <div class="bg-mid-bg pad-size-1">Item 8</div>
  </div>
</div>

<h2 id="reel">Reel</h2>
<p><code>.reel</code></p>

<p>
  The Reel provides a scrollable, overflow container. To add a scrollbar, you
  apply the
  <a href="/design-system/css-utilities/#scrollbar"
    ><code>.scrollbar</code> utility</a
  >, which provides consistent scrollbars where needed.
</p>

<h3>Configuration</h3>

<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--reel-item-width</code></td>
        <td><code>33.333%</code> (one third)</td>
        <td>This defines the size of each child element.</td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Exceptions</h3>

<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Exception</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>.reel[data-scroll='snap']</code></td>
        <td>Enables scroll snapping</td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>

<div class="breakout gap-top-size-1">
  <div class="reel">
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
  </div>
</div>

<h4>With scrollbar</h4>

<div class="breakout gap-top-size-1">
  <div class="reel scrollbar">
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
  </div>
</div>

<h4>With scroll snapping</h4>

<div class="breakout gap-top-size-1">
  <div class="reel scrollbar" data-scroll="snap">
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
    <div class="region bg-mid-bg pad-inline-size-1">Item</div>
  </div>
</div>

<h2 id="repel">Repel</h2>
<p>
  A little layout that pushes items away from each other where there is space in
  the viewport and stacks on small viewports.
</p>
<p><code>.repel</code></p>

<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--gutter</code></td>
        <td><code>$global-gutter</code></td>
        <td>This defines the space between items.</td>
      </tr>
      <tr>
        <td><code>--repel-vertical-alignment</code></td>
        <td><code>20rem</code></td>
        <td>
          How items should align vertically. Can be any acceptable
          <a
            href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container"
            >flexbox alignment value.</a
          >.
        </td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>
<div class="breakout gap-top-size-1">
  <div class="repel">
    <div class="bg-mid-bg pad-size-1">Item 1 repels item 2</div>
    <div class="bg-mid-bg pad-size-1">Item 2 repels item 1</div>
  </div>
</div>

<h2 id="sidebar">Sidebar</h2>
<p><code>.sidebar</code></p>

<p>
  A layout that allows you to have a flexible main content area and a
  &quot;fixed&quot; width sidebar that sits on the left or right. If there is
  not enough viewport space to fit both the sidebar width <em>and</em> the main
  content minimum width, they will stack on top of each other
</p>

<h3>Configuration</h3>
<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--gutter</code></td>
        <td><code>$global-gutter</code></td>
        <td>This defines the space between the sidebar and main content.</td>
      </tr>
      <tr>
        <td><code>--sidebar-target-width</code></td>
        <td><code>20rem</code></td>
        <td>How large the sidebar should be</td>
      </tr>
      <tr>
        <td><code>--sidebar-content-min-width</code></td>
        <td><code>50%</code></td>
        <td>The minimum size of the main content area</td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Exceptions</h3>

<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Exception</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>.sidebar[data-direction='rtl']</code></td>
        <td>Flips the sidebar to be on the right</td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>

<p>A standard sidebar.</p>

<div class="breakout gap-top-size-1">
  <div class="sidebar">
    <div class="bg-mid-bg pad-size-1">I am the sidebar</div>
    <div class="flow bg-mid-bg pad-size-1">
      <h4>I am the content</h4>
      <p>
        Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur
        purus sit amet fermentum.
      </p>
      <p>
        Cum sociis natoque penatibus et magnis dis parturient montes, nascetur
        ridiculus mus. Vestibulum id ligula porta felis euismod semper.
      </p>
    </div>
  </div>
</div>

<p>Flipped sidebar.</p>

<div class="breakout gap-top-size-1">
  <div class="sidebar" data-direction="rtl">
    <div class="flow bg-mid-bg pad-size-1">
      <h4>I am the content</h4>
      <p>
        Etiam porta sem malesuada magna mollis euismod. Cras mattis consectetur
        purus sit amet fermentum.
      </p>
      <p>
        Cum sociis natoque penatibus et magnis dis parturient montes, nascetur
        ridiculus mus. Vestibulum id ligula porta felis euismod semper.
      </p>
    </div>
    <div class="bg-mid-bg pad-size-1">I am the RTL sidebar</div>
  </div>
</div>

<h2>Switcher</h2>
<p><code>.switcher</code></p>

<p>
  A layout that allows you to lay <strong>2</strong> items next to each other
  until there is not enough horizontal space to allow that.
</p>

<h3>Configuration</h3>
<div class="table-wrapper breakout">
  <table>
    <thead>
      <tr>
        <th>Property</th>
        <th>Default value</th>
        <th>Description</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><code>--switcher-gutter</code></td>
        <td><code>$global-gutter</code></td>
        <td>This defines the space between each item</td>
      </tr>
      <tr>
        <td><code>--switcher-vertical-alignment</code></td>
        <td><code>flex-start</code></td>
        <td>
          How items should align vertically. Can be any acceptable
          <a
            href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Aligning_Items_in_a_Flex_Container"
            >flexbox alignment value.</a
          >
        </td>
      </tr>
      <tr>
        <td><code>--switcher-target-container-width</code></td>
        <td><code>30rem</code></td>
        <td>
          How large the container needs to be to allow items to sit inline with
          each other
        </td>
      </tr>
    </tbody>
  </table>
</div>

<h3>Examples</h3>

<div class="breakout gap-top-size-1">
  <div class="switcher">
    <div class="bg-mid-bg pad-size-1">Item 1</div>
    <div class="bg-mid-bg pad-size-1">Item 2</div>
  </div>
</div>

{% endblock %}
